const Page = require("../models/pages");
const Components = require("../models/components");
const path = require("path");
const shell = require("shelljs");
const Services = require("../services/page");
// 获取相同数组
const getCommonArray = (arr1, arr2) => {
  return arr1.filter((item) => arr2.includes(item));
};

async function delp(comms, callback) {
  if (comms.length === 0) {
    return;
  }

  const comm = comms[0];
  await callback(comm);

  // 递归调用 dep 处理剩余的 comms
  await delp(comms.slice(1), callback);
}

const dep = async (comm, fun) => {
  if (!Array.isArray(comm) || comm.length === 0) {
    return;
  }
  const promises = comm.map(async (a) => {
    try {
      await fun(a);

      if (a.children && Array.isArray(a.children) && a.children.length > 0) {
        await dep(a.children, fun);
      }
    } catch (error) {
      console.error(`Error processing item ${JSON.stringify(a)}:`, error);
      throw error; // 根据需求决定是否重新抛出错误
    }
  });

  return await Promise.all(promises);
};
const writeFile = async (id, project, url, components, modals, name, grids) => {
  return new Promise(async (resolve) => {
    const comms = [...components];
    await Services.PageRouteService(id, project, url, name); // 生成路由
    let strcomm = [];
    await dep(comms, async (comm) => {
      comm = { ...comm, ...comm.attrs };
      const code = comm.componentKey;
      const c = await Components.findOne({ code: code });
      if (comm && comm.componentKey === "table") {
        Object.keys(comm).forEach((key) => {
          const validKeyPattern = /^[\w-]+-(\w+)$/;
          if (key.match(validKeyPattern) && !Object.keys(comm._esr).includes(key)) {
            delete comm[key];
          }
        });
      }
      delete comm.attrs;
      delete comm._esr;

      await Services.PagePackageService(c.content, project.code); // 加入到package.json
      await Services.PageApiService(project.code, comm); // 生成apis
      strcomm.push({
        comm,
        apiUrl: comm.apiUrl || (comm.options && comm.options.indexOf("Filters") === -1 ? comm.options : null),
        componentKey: code,
        commstr: await Services.PageComponentsService(c.content, project.code, code),
      }); // 组件加入到项目
      await Services.PageFilterService(comm, project.code, code);
    });
    const executes = await Services.PageExecuteService(strcomm, modals);
    console.log(executes.comms, "strcomm");

    modals = modals.map((a) => {
      delete a.show;
      return a;
    });

    await Services.PageViewService(
      id,
      project.code,
      executes,
      modals,
      strcomm,
      url,
      grids
    ); // 页面加入到项目
    resolve(executes.comms);
  });
};

const prettierFile = async (project) => {
  const dir = path.resolve(__dirname, "../../projects/" + project.code);
  shell.cd(dir);
  stdout = await shell.exec(
    `prettier --write "${dir}/src/**/*.{js,jsx,ts,tsx,vue,scss,css}"`
  );
  stdout = await shell.exec(`prettier --write "${dir}/package.json"`);
};

class PageCtl {
  async get(ctx) {
    let limit = ctx.query.limit ? ctx.query.limit : 10;
    let page = ctx.query.page ? ctx.query.page : 1;

    let where = {};
    const filters = ["name"];
    filters.forEach((key) => {
      if (ctx.query[key]) {
        if (key === "name") {
          where[key] = new RegExp(ctx.query[key]);
        } else {
          where[key] = ctx.query[key];
        }
      }
    });

    let _Page = await Page.find(where);
    limit = parseInt(limit);
    let skip = limit * (parseInt(page) - 1);
    let total = _Page.length;
    let list = [];

    if (total > 0) {
      list = await Page.find(where).limit(limit).skip(skip).sort({ _id: -1 });
    }

    ctx.body = {
      code: 200,
      msg: "success",
      data: {
        limit: limit,
        page: page,
        list: list,
        total: total,
      },
    };
  }

  async all(ctx) {
    let _Page = await Page.find({});
    ctx.body = {
      code: 200,
      msg: "success",
      data: _Page,
    };
  }

  async create(ctx) {
    const name = ctx.request.body.name;
    const project = ctx.request.body.project;
    const url = ctx.request.body.url;
    const exit = await Page.findOne({
      name: name,
    });
    if (exit) {
      ctx.body = {
        errCode: -1,
        msg: "页面已存在",
      };
      return;
    }

    const _Page = await new Page({
      name,
      project,
      url,
      createAt: new Date(),
      updateAt: new Date(),
    }).save();

    ctx.body = {
      code: 200,
      msg: "success",
      data: _Page,
    };
  }

  async modify(ctx) {
    const _id = ctx.request.body._id;
    const name = ctx.request.body.name;
    const project = ctx.request.body.project;
    const url = ctx.request.body.url;
    const components = ctx.request.body.components || [];
    const exit = await Page.findOne({
      $or: [{ name: name }],
      _id: { $ne: _id },
    });
    if (exit) {
      ctx.body = {
        code: -1,
        msg: "页面已存在",
      };
      return;
    }

    const _Page = await Page.updateOne(
      { _id: _id },
      {
        name,
        project,
        url,
        components,
        updateAt: new Date(),
      }
    );

    ctx.body = {
      code: 200,
      msg: "success",
      data: _Page,
    };
  }

  async setOff(ctx) {
    const id = ctx.request.body.id;
    const components = ctx.request.body.components;
    const modals = ctx.request.body.modals;
    const project = ctx.request.body.project;
    const url = ctx.request.body.url;
    const name = ctx.request.body.name;
    const grids = ctx.request.body.grids;

    let _Page = await Page.findOne({ _id: id });

    const comms = await writeFile(
      id,
      project,
      url,
      components,
      modals,
      name,
      grids
    );
    _Page = await Page.updateOne(
      { _id: id },
      {
        name,
        project,
        url,
        components: comms,
        modals,
        grids,
        updateAt: new Date(),
      }
    );

    ctx.body = {
      code: 200,
      msg: "success",
      data: _Page,
    };
    prettierFile(project);
  }

  async info(ctx) {
    const id = ctx.query.id;
    const _Page = await Page.findOne({
      _id: id,
    }).populate("project");
    ctx.body = {
      code: 200,
      msg: "success",
      data: _Page,
    };
  }
  async remove(ctx) {
    const id = ctx.params.id;
    await Page.deleteOne({
      _id: id,
    });

    ctx.body = {
      code: 200,
      msg: "success",
    };
  }
}

module.exports = new PageCtl();
